package com.cskaoyan.wordmemorize.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cskaoyan.wordmemorize.common.constant.ResultCodeEnum;
import com.cskaoyan.wordmemorize.common.aspect.operate.OperateLog;
import com.cskaoyan.wordmemorize.common.aspect.operate.OperateLogConstant;
import com.cskaoyan.wordmemorize.common.exception.BusinessException;
import com.cskaoyan.wordmemorize.converter.VocCategoryConverter;
import com.cskaoyan.wordmemorize.dao.entity.VocBookDO;
import com.cskaoyan.wordmemorize.dao.entity.VocCategoryDO;
import com.cskaoyan.wordmemorize.dao.mapper.VocBookMapper;
import com.cskaoyan.wordmemorize.dao.mapper.VocCategoryMapper;
import com.cskaoyan.wordmemorize.dto.admin.DeleteBookCategoryOperateDTO;
import com.cskaoyan.wordmemorize.dto.admin.PageDTO;
import com.cskaoyan.wordmemorize.dto.admin.VocCategoryDTO;
import com.cskaoyan.wordmemorize.request.BatchDeleteCommand;
import com.cskaoyan.wordmemorize.request.PageRequest;
import com.cskaoyan.wordmemorize.request.VocCategoryCommand;
import com.cskaoyan.wordmemorize.service.VocCategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.util.List;
import java.util.stream.Collectors;

@Service
public class VocCategoryServiceImpl implements VocCategoryService {


    @Autowired
    VocCategoryMapper vocCategoryMapper;


    @Autowired
    VocCategoryConverter vocCategoryConverter;

    @Autowired
    VocBookMapper vocBookMapper;

    @Override
    public PageDTO<VocCategoryDTO> getBookCategories(PageRequest pageQuery) {

        if (pageQuery.getPageNum() == null) {
            // 查询所有的书籍类目
            List<VocCategoryDO> vocCategoryDOs = vocCategoryMapper.selectList(null);

            return vocCategoryConverter.bookCategoryList2Page(vocCategoryDOs, (long) vocCategoryDOs.size());
        }

        // 需要分页
        Page<VocCategoryDO> pageParam = new Page<>(pageQuery.getPageNum(), pageQuery.getCount());
        LambdaQueryWrapper<VocCategoryDO> vocCategoryWrapper = new LambdaQueryWrapper<>();
        if (pageQuery.getKeyword() != null) {
            vocCategoryWrapper.like(VocCategoryDO::getCategoryName, pageQuery.getKeyword());
        }
        Page<VocCategoryDO> vocCategoryPage = vocCategoryMapper.selectPage(pageParam, vocCategoryWrapper);


        return vocCategoryConverter.bookCategoryList2Page(vocCategoryPage.getRecords(), vocCategoryPage.getTotal());
    }

    @Override
    public VocCategoryDTO getBookCategory(Long categoryId) {
        LambdaQueryWrapper<VocCategoryDO> vocCategoryWrapper = new LambdaQueryWrapper<>();
        vocCategoryWrapper.eq(VocCategoryDO::getId, categoryId);
        VocCategoryDO vocCategoryDO = vocCategoryMapper.selectOne(vocCategoryWrapper);
        return vocCategoryConverter.bookCategoryEntity2DTO(vocCategoryDO);
    }

    @OperateLog(dataType = "书籍类目", operateType = OperateLogConstant.OPERATE_ADD)
    @Override
    public Long addBookCategory(VocCategoryCommand command) {
        VocCategoryDO vocCategoryDO = vocCategoryConverter.bookCategoryCommand2Entity(command);
        LambdaQueryWrapper<VocCategoryDO> queryWrapper = new LambdaQueryWrapper<>();
        // todo:判断增加的书籍类目在数据库是否已经存在,若不存在则添加，若存在则抛出异常
        queryWrapper.eq(VocCategoryDO::getCategoryName, vocCategoryDO.getCategoryName());
        VocCategoryDO judgeVocCategoryDO = vocCategoryMapper.selectOne(queryWrapper);
        if (judgeVocCategoryDO != null) {
            // todo:judgeVocCategoryDO不为null说明存在，抛出异常
            throw new BusinessException(ResultCodeEnum.BOOK_CATEGORY_EXISTED);
        } else {
            // todo:judgeVocCategoryDO为null说明不存在，插入数据
            vocCategoryMapper.insert(vocCategoryDO);
        }
        return null;
    }

    @OperateLog(dataType = "书籍类目", operateType = OperateLogConstant.OPERATE_UPDATE)
    @Transactional
    @Override
    public void updateBookCategory(VocCategoryCommand command) {
        VocCategoryDO vocCategoryDO = vocCategoryConverter.bookCategoryCommand2Entity(command);
        LambdaQueryWrapper<VocCategoryDO> queryWrapper = new LambdaQueryWrapper<>();
        LambdaUpdateWrapper<VocCategoryDO> updateWrapper = new LambdaUpdateWrapper<>();
        LambdaUpdateWrapper<VocBookDO> vocBookDOWrapper = new LambdaUpdateWrapper<>();
        // todo:判断修改后的书籍类目名称在数据库是否存在,若不存在则修改，若存在则抛出异常
        queryWrapper.eq(VocCategoryDO::getCategoryName, vocCategoryDO.getCategoryName());
        VocCategoryDO judgeVocCategoryDO = vocCategoryMapper.selectOne(queryWrapper);
        if (judgeVocCategoryDO != null) {
            // todo:judgeVocCategoryDO不为null说明存在，抛出异常
            throw new BusinessException(ResultCodeEnum.BOOK_CATEGORY_EXISTED);
        } else {
            // todo:judgeVocCategoryDO为null说明不存在，修改book_category
            updateWrapper.eq(VocCategoryDO::getId, vocCategoryDO.getId());
            vocCategoryMapper.update(vocCategoryDO, updateWrapper);
            // todo:修改voc_book中的bc_name字段
            vocBookDOWrapper.eq(VocBookDO::getBcId, vocCategoryDO.getId())
                    .set(VocBookDO::getBcName, vocCategoryDO.getCategoryName());
            vocBookMapper.update(vocBookDOWrapper);
        }
    }

    // todo:删除指定的书籍类目
    @OperateLog(dataType = "书籍类目", operateType = OperateLogConstant.OPERATE_SINGLE_DELETE)
    @Transactional
    @Override
    public DeleteBookCategoryOperateDTO deleteBookCategory(Long categoryId) {
        LambdaQueryWrapper<VocCategoryDO> vocCategoryWrapper = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<VocBookDO> vocBookWrapper = new LambdaQueryWrapper<>();
        vocCategoryWrapper.eq(VocCategoryDO::getId, categoryId);
        VocCategoryDO vocCategoryDO = vocCategoryMapper.selectOne(vocCategoryWrapper);
        // todo:判断要删除的书籍类目id在数据库是否存在,若存在则删除，若不存在则抛出异常
        if (vocCategoryDO == null) {
            throw new BusinessException(ResultCodeEnum.BOOK_CATEGORY_NOT_EXISTED);
        } else {
            // todo:删除书籍类目表book_category中对应id的书籍类目
            vocCategoryMapper.deleteById(categoryId);
            // todo:删除voc_book表中属于该id书籍类目下的书籍
            vocBookWrapper.eq(VocBookDO::getBcId, categoryId);
            vocBookMapper.delete(vocBookWrapper);
        }
        return vocCategoryConverter.bookCategoryDOToDeleteCategoryDTO(vocCategoryDO);
    }

    // todo:批量删除书籍类目
    @OperateLog(dataType = "书籍类目", operateType = OperateLogConstant.OPERATE_BATCH_DELETE)
    @Transactional
    @Override
    public List<DeleteBookCategoryOperateDTO> deleteBookCategories(BatchDeleteCommand command) {
        // todo:将BatchDeleteCommand中String类型的id转换为Long类型
        List<Long> ids = command.getIds().stream().map(Long::valueOf).collect(Collectors.toList());
        LambdaQueryWrapper<VocCategoryDO> vocCategoryWrapper = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<VocBookDO> vocBookWrapper = new LambdaQueryWrapper<>();
        vocCategoryWrapper.in(VocCategoryDO::getId, ids);
        List<VocCategoryDO> vocCategoryDOs = vocCategoryMapper.selectList(vocCategoryWrapper);
        List<Long> bcId = vocCategoryDOs.stream().map(VocCategoryDO::getId).collect(Collectors.toList());
        vocBookWrapper.in(VocBookDO::getBcId, bcId);
        // todo:判断要删除的书籍类目id在数据库是否存在,若存在则删除，若不存在则抛出异常
        if (ids.size() != vocCategoryDOs.size()) {
            throw new BusinessException(ResultCodeEnum.BOOK_CATEGORY_NOT_EXISTED);
        } else {
            // todo:删除书籍类目表book_category中对应id的书籍类目
            vocCategoryMapper.delete(vocCategoryWrapper);
            // todo:删除voc_book表中属于该id书籍类目下的书籍
            vocBookMapper.delete(vocBookWrapper);
        }
        return vocCategoryConverter.bookCategoryDOsToDeleteCategoryDTOs(vocCategoryDOs);
    }
}
